<?php

class Modules {

    private $_hostName = null;
    private $_userName = null;
    private $_password = null;
    private $_database = null;
    private $_resource = null;
    private $_connection = null;

    function __construct() {
        
    }

    public function setConfig($aryConfig) {
        $this->_hostName = $aryConfig['hostName'];
        $this->_userName = $aryConfig['userName'];
        $this->_password = $aryConfig['password'];
        $this->_database = $aryConfig['database'];
    }

    /**
     * connect to database
     * @return <type>
     */
    public function _connection() {
        $connection = @mysql_connect($this->_hostName, $this->_userName, $this->_password);
        $this->_connection = $connection;
        if (!$connection) {
            $this->writeLog('Khong the ket noi voi server ' . mysql_error());
            return false;
        }
        if (!mysql_select_db($this->_database, $connection)) {
            $this->writeLog('Khong the ket noi to database ' . mysql_error());
            return false;
        }
        return $connection;
    }

    /**
     * escape \
     * @param <type> $value
     * @return <type>
     */
    public function escape($value) {
        if (get_magic_quotes_gpc()) {
            $value = stripcslashes($value);
        }
        return mysql_real_escape_string($value);
    }

    private function replaceArrayBin($sql, array $aryBin) {
//        $aryBin = array_map($this->escape, $aryBin);
        $sql = str_replace('?', "'%s'", $sql);
        //get the safe sql string
        return vsprintf($sql, $aryBin);
    }

    /**
     * Thuc thi sql
     * @param <type> $sql
     * @return <type>
     */
    public function query($sql, array $aryBin = null) {
        $intOk = 1;
        mysql_query("SET NAMES 'UTF8'");
        if (true === isset($aryBin) && true === is_array($aryBin)) {
            $sql = $this->replaceArrayBin($sql, $aryBin);
        }
        $this->_resource = mysql_query($sql);
        if (!$this->_resource) {
            $this->writeLog(mysql_error());
            $intOk = 0;
        }
        return $intOk;
    }

    public function _close() {
        if (is_resource($this->_connection)) {
            mysql_close($this->_connection);
        }
    }

    public function _freeResult() {
        if (is_resource($this->_resource)) {
            mysql_free_result($this->_resource);
        }
    }

    public function Excute($sql, array $aryBin = null) {
        $this->_connection();
        if (true === isset($aryBin) && true === is_array($aryBin)) {
            $sql = $this->replaceArrayBin($sql, $aryBin);
        }
        $intOk = $this->query($sql);
        return $intOk;
    }

    /**
     * Lay du lieu tu database dua vao mang
     * @param <type> $sql
     * @param <type> $aryResultData
     * @return int
     */
    public function getArray($sql, &$aryResultData, array $aryBin = null) {
        $intOk = 1;

        $this->_connection();

        if (true === isset($aryBin) && true === is_array($aryBin)) {
            $sql = $this->replaceArrayBin($sql, $aryBin);
        }

        $intOk = $this->query($sql);

        $result = $this->_resource;

        $aryResultData = array();
        while ($row = mysql_fetch_assoc($result)) {
            $aryResultData[] = $row;
        }
        if (!isset($aryResultData[0])) {
            $intOk = 0;
        }
        return $intOk;
    }

    /**
     * Lay id vua duoc insert vao database
     * @return <type>
     */
    public function getLastInsertedID() {
        return mysql_insert_id();
    }

    /**
     * Insert du lieu vao database
     * @param <type> $table
     * @param array $aryData
     * key cua $aryData la field trong database
     * @return int
     */
    public function insert($table, array $aryData) {
        $this->_connection();
        $insertField = array();
        $insertValue = array();

        foreach ($aryData as $field => $value) {
            array_push($insertField, "`" . $field . "`");
            array_push($insertValue, "'" . $this->escape($value) . "'");
        }
        $fieldString = implode(",", $insertField);
        $valueString = implode(",", $insertValue);
        //normal insert
        $sql = "INSERT INTO  " . $table . "(" . $fieldString . ") VALUES (" . $valueString . ")";
        $intOk = $this->query($sql);
        return $intOk;
    }

    /**
     * update du lieu theo dieu kien nao do
     * @param <type> $table
     * @param array $aryData
     * Key cua $aryData la ten field trong database
     * @param array $condition
     * @return <type>
     */
    public function update($table, array $aryData, array $condition = null) {
        $this->_connection();
        $set = '';
        foreach ($aryData as $field => $value) {
            if ($value == null) {
                // keep a null value
                $set .= $field . " = null, ";
            } else {
                $set .= $field . " = '" . $this->escape($value) . "', ";
            }
        }
        $set = substr($set, 0, -2);
        $sql = "UPDATE " . $table . " SET " . $set;
        //merge condition
        if (isset($condition) && true == is_array($condition)) {
            $sql .= $this->buildCondition($condition);
        }
        $intOk = $this->query($sql);
        return $intOk;
    }

    /*
     * build condition
     *
     * @param <array> $condition
     * @example
     * $condition = array(
     *      array(
     *          'field'     =>  'member_i_member_id',
     *          'math'      =>  '>=',
     *          'value'     =>  '50'
     *      ),
     *      array(
     *          'keyword'   =>  'AND',
     *          'field'     =>  'member_i_class',
     *          'math'      =>  '<',
     *          'value'     =>  '100'
     *      ),
     *      array(
     *          'keyword'   =>  'OR',
     *          'field'     =>  'member_i_del_flg',
     *          'math'      =>  '=',
     *          'value'     =>  '0'
     *      ),
     *      array(
     *          'keyword'   =>  'OR',
     *          'field'     =>  'member_v_login_name',
     *          'math'      =>  'LIKE',
     *          'value'     =>  'phund%'
     *      ),
     * );
     *
     * @example
     * $condition = array(
     *      array(
     *          'keyword'   =>  'AND',
     *          'field'     =>  'member_i_member_id',
     *          'math'      =>  'IN',
     *          'value'     =>  '(1,2,3)'
     *      ),
     * );
     *
     * @return <array>
     * @example
     * array(
     *      'sql'       =>  "WHERE member_i_member_id >= ? AND member_i_class < ? OR member_i_del_flg = ? OR member_v_login_name LIKE ?",
     *      'aryBin'    =>  array(50, 100, 0, 'phund%');
     * );
     * @desc:
     * 1) 'sql' just for sample
     * 2) not handle for () in WHERE
     * 3) not full handle for IN (because we not put value in $aryBin)
     * @todo: FIX ME
     */

    protected function buildCondition(array $condition) {
        $sql = '';
        $space = ' ';
        if (true === isset($condition[0])) {
            //create sql (contain ?) and array bin
            foreach ($condition as $key => $sub) {
                //is WHERE
                if (false == isset($sub['keyword'])) {
                    $sub['keyword'] = 'WHERE';
                }
                $sql .= $space . $sub['keyword'] . $space . $sub['field'] . $space . $sub['math'] . $space . $sub['value'];
            }
        }
        return $sql;
    }

    public function paging($sql, $currentPage, $recordPerpage, &$aryResultData, array $aryBin = null) {
        if ($currentPage == 0)
            $currentPage = 1;

        $offset = ($currentPage - 1) * $recordPerpage;

        $sqlPage = $sql . ' LIMIT ' . $offset . ',' . $recordPerpage;

        $intOk = $this->getArray($sqlPage, $aryRecordData, $aryBin);
        if ($intOk == 1) {
            $this->query($sql, $aryBin);
            $totalRecord = $this->getTotalRecord($sql);
            $totalPage = ceil($totalRecord / $recordPerpage);
        } else {
            $totalRecord = 0;
            $totalPage = 0;
        }

        $aryResultData = array(
            'paging' => array(
                'total_page' => $totalPage,
                'total_record' => $totalRecord,
                'current_page' => $currentPage,
                'record_per_page' => $recordPerpage,
            ),
            'data' => $aryRecordData
        );

        return $intOk;
    }

    public function getTotalRecord($sql) {
        $total = 0;
        if (true == is_resource($this->_resource)) {
            $total = mysql_num_rows($this->_resource);
        }

        return $total;
    }

    public function writeLog($data) {
        $logFile = dirname(dirname(__FILE__)) . DIRECTORY_SEPARATOR . 'log' . DIRECTORY_SEPARATOR . 'log.txt';
        $fp = fopen($logFile, "w");
        fputs($fp, $data);
        fclose($fp);
    }

}

?>
